home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / bin / dh_pysupport < prev    next >
Text File  |  2008-01-05  |  13KB  |  375 lines

  1. #!/usr/bin/perl -w
  2.  
  3. =head1 NAME
  4.  
  5. dh_pysupport - use the python-support framework to handle Python modules
  6.  
  7. =cut
  8.  
  9. use strict;
  10. use File::Find;
  11. use Debian::Debhelper::Dh_Lib;
  12.  
  13. =head1 SYNOPSIS
  14.  
  15. B<dh_pysupport> [S<I<debhelper options>>] [-V I<X.Y>] [-X I<item> [...]] [-n] [S<I<module dirs ...>>]
  16.  
  17. =head1 DESCRIPTION
  18.  
  19. dh_pysupport is a debhelper program that will scan your package, detect
  20. public modules in I</usr/share/python-support> and generate appropriate
  21. postinst/prerm scripts to byte-compile modules installed there for all
  22. available python versions.
  23.  
  24. It will also look for private Python modules and will byte-compile them
  25. with the current Python version. You may have to list the directories
  26. containing private Python modules.
  27.  
  28. If a file named I<debian/pyversions> exists, it is installed in 
  29. I</usr/share/python-support/$PACKAGE/.version>.
  30.  
  31. Appropriate dependencies on python-support, python and pythonI<X.Y> are
  32. put in ${python:Depends}.  The ${python:Versions} and ${python:Provides} 
  33. optional substitution variables are made available as well.
  34.  
  35. =head1 OPTIONS
  36.  
  37. =over 4
  38.  
  39. =item I<module dirs>
  40.  
  41. If your package installs private python modules in non-standard directories, you
  42. can make dh_pysupport check those directories by passing their names on the
  43. command line. By default, it will check /usr/lib/$PACKAGE,
  44. /usr/share/$PACKAGE, /usr/lib/games/$PACKAGE and /usr/share/games/$PACKAGE
  45.  
  46. =item B<-n>, B<--noscripts>
  47.  
  48. Do not modify postinst/postrm scripts.
  49.  
  50. =item B<-d>
  51.  
  52. This option is deprecated.
  53.  
  54. =item B<-V> I<X.Y>
  55.  
  56. Force private modules to be bytecompiled with the specific I<X.Y> python version, regardless of the default python version on the system.
  57.  
  58. =item B<-X> I<item>, B<--exclude=>I<item>
  59.  
  60. Exclude files that contain "item" anywhere in their filename from being
  61. taken into account to generate the python dependency. You may use this
  62. option multiple times to build up a list of things to exclude.
  63.  
  64. =back
  65.  
  66. =head1 CONFORMS TO
  67.  
  68. Python policy as of 2006-08-10
  69.  
  70. =cut
  71.  
  72. init();
  73.  
  74. sub next_minor_version {
  75.     my $version = shift;
  76.     # Handles 2.10 -> 2.11 gracefully
  77.     my @items = split(/\./, $version);
  78.     $items[1] += 1;
  79.     $version = join(".", @items);
  80.     return $version;
  81. }
  82.  
  83. sub specified_deps_in_package {
  84.     my $package = shift;
  85.     my $curpackage = 0;
  86.     my @deps = ();
  87.     open (CONTROL, 'debian/control') || error("cannot read debian/control: $!\n");
  88.     while (<CONTROL>) {
  89.         chomp;
  90.         s/\s+$//;
  91.         if (/^Package:\s*(.*)$/ && $package eq $1) {
  92.             $curpackage = 1;
  93.         }
  94.         if ($curpackage == 2) {
  95.             if (/^\s+(.*)$/) {
  96.                 push @deps, split ",",$1;
  97.                 if ($1 !~ /,$/) {
  98.                     return @deps;
  99.                 }
  100.             } else {
  101.                 return @deps;
  102.             }
  103.         }
  104.         if ($curpackage && /^Python-Depends:\s*(.*)$/) {
  105.             @deps = split ",",$1;
  106.             if ($1 =~ /,$/) {
  107.                 $curpackage = 2;
  108.             } else {
  109.                 return @deps;
  110.             }
  111.         }
  112.     }
  113.     return @deps;
  114. }
  115.  
  116. sub trim {
  117.     my $tmp = shift;
  118.     $tmp =~ s/^\s+//;
  119.     $tmp =~ s/\s+$//;
  120.     return $tmp;
  121. }
  122.  
  123. # The current default python version
  124. my $default=`readlink /usr/bin/python`;
  125. $default =~ s/^python//;
  126. chomp $default;
  127.  
  128. # All supported versions
  129. my $allversions_string=`pysupport-parseversions --all`;
  130. chomp $allversions_string;
  131. my @allversions=split " ", $allversions_string;
  132.  
  133. # Use a specific version for private modules (doesn't affect public modules)
  134. my $useversion;
  135. if($dh{V_FLAG_SET}) {
  136.     $useversion = $dh{V_FLAG};
  137.     if (! grep { $_ eq $useversion } @allversions) {
  138.         error("Unknown python version $useversion");
  139.     }
  140. }
  141.  
  142. foreach my $package (@{$dh{DOPACKAGES}}) {
  143.     my $tmp = tmpdir($package);
  144.     my $have_pydep=0; # This variable tells whether we have added some dependency
  145.               # on python one way or another.
  146.     my @specified_deps = specified_deps_in_package ($package);
  147.     my $do_scripts = "";
  148.     
  149.     # 1) Handle public python modules
  150.     # Move them to the python-support directories
  151.     doit (("pysupport-movemodules",$tmp));
  152.     # Then look for what the script found
  153.     foreach my $ps_dir (glob("$tmp/usr/share/python-support/*")) {
  154.         if (-d $ps_dir && ! excludefile($ps_dir)) {
  155.             my $verfile = "debian/pyversions";
  156.                 if (-f $verfile) {
  157.                     # TODO: debian/package.pyversions ?
  158.                     doit("install","-p","-m644",$verfile,"$ps_dir/.version");
  159.                 }
  160.                 my $ext_dir=$ps_dir;
  161.                 $ext_dir =~ s,/usr/share/,/usr/lib/,;
  162.              my $supported;
  163.                 if (-d $ext_dir) {
  164.                     if (-f "$ps_dir/.version") {
  165.                         # Just ignore the .version file when there are extensions.
  166.                         # The extensions dictate which versions to handle.
  167.                         doit(("rm","-f","$ps_dir/.version"));
  168.                     }
  169.                     my @provides;
  170.                     foreach my $pydir (glob("$ext_dir/python*")) {
  171.                         if (-d $pydir && $pydir =~ m/python(\d+).(\d+)/) {
  172.                             push @provides, "$1.$2";
  173.                         }
  174.                     }
  175.                     my $a=join ",",@provides;
  176.                     error("$ext_dir doesn't contain modules for any supported python version") if (! $a);
  177.                     $supported=`echo $a | pysupport-parseversions --minmax`;
  178.             } elsif (-f "$ps_dir/.version") {
  179.                     $supported=`pysupport-parseversions --minmax $ps_dir/.version`;
  180.                 } else {
  181.                     my $doko_versions=`pysupport-parseversions --raw --pycentral debian/control`;
  182.                     chomp $doko_versions;
  183.                     if ($doko_versions !~ /not found/) {
  184.                         print "Compatibility mode: using detected XS-Python-Version.\n";
  185.                         complex_doit("echo $doko_versions > $ps_dir/.version");
  186.                         $supported=`pysupport-parseversions --minmax --pycentral debian/control`;
  187.                     } else {
  188.                     $supported=`echo - | pysupport-parseversions --minmax`;
  189.                     }
  190.             }
  191.                 # Add the packages explicitly asked by the maintainer
  192.                 foreach my $dep (@specified_deps) {
  193.                     $dep = trim $dep;
  194.                     addsubstvar($package, "python:Depends", $dep);
  195.                 }
  196.                 my @ar=split "\n",$supported;
  197.                 my @provides=split " ",$ar[0];
  198.                 foreach my $pyversion (@provides) {
  199.                     # Generate the useless versions field
  200.                     addsubstvar($package, "python:Versions", $pyversion);
  201.                     # ... and the provides field
  202.                 if ($package =~ /^python-/) {
  203.                         my $virtual = $package;
  204.                     $virtual =~ s/^python-/python$pyversion-/;
  205.                     addsubstvar($package, "python:Provides", $virtual);
  206.                     }
  207.                     # Use the provides fields in packages dependended upon
  208.                     foreach my $dep (@specified_deps) {
  209.                     $dep = trim $dep;
  210.                         # I have no idea why this wouldn't be the case, but well
  211.                         if ($dep =~ /^python-(\S+)/) {
  212.                             addsubstvar($package, "python:Depends", "python$pyversion-$1");
  213.                         }
  214.                     }
  215.                 }
  216.                    my @minmax=split " ",$ar[1];
  217.                    my $minversion=$minmax[0];
  218.                 if ( grep { $_ eq $default } @provides ) {
  219.                     # The default version is in the supported versions
  220.                     if ($minversion ne "None") {
  221.                         addsubstvar($package, "python:Depends", "python (>= $minversion)");
  222.                     $have_pydep=1;
  223.                     }
  224.                 } elsif ($minversion ne "None") {
  225.                     # The default version is less than all supported versions
  226.                     addsubstvar($package, "python:Depends", "python (>= $minversion) | python$minversion");
  227.                 $have_pydep=1;
  228.                 } else {
  229.                     error("The default python version is greater than all supported versions");
  230.                 }
  231.                 my $maxversion=$minmax[1];
  232.                 if ($maxversion ne "None") {
  233.                 $maxversion = next_minor_version($maxversion);
  234.                 addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  235.                 $have_pydep=1;
  236.             }
  237.             $ps_dir =~ s,^$tmp/usr/share/python-support/,,;
  238.             $do_scripts = "$do_scripts $ps_dir";
  239.         }
  240.     }
  241.  
  242.         # 2) Look for private python modules
  243.     my @dirs = ("/usr/lib/$package", "/usr/share/$package",
  244.             "/usr/lib/games/$package", "/usr/share/games/$package", @ARGV );
  245.     @dirs = grep -d, map "$tmp$_", @dirs;
  246.         my @dirlist;
  247.         my $need_pydep=0;
  248.         my $strong_pydep=0;
  249.     my %need_verdep = ();
  250.     foreach (@allversions) {
  251.         $need_verdep{$_} = 0;
  252.     }
  253.         if (@dirs) {
  254.                 foreach my $curdir (@dirs) {
  255.                         my $has_module = 0;
  256.                         my $has_extension = 0;
  257.                         find sub {
  258.                                 return unless -f;
  259.                                 return if excludefile($File::Find::name);
  260.                                 if (/.py$/) {
  261.                                     $has_module=1;
  262.                                     doit(("rm","-f",$_."c",$_."o"));
  263.                                 }
  264.                                 if (/.so$/ &&
  265.                                     `nm -Du "$_" | grep "U Py_InitModule"` &&
  266.                                     ! `objdump -p "$_" | grep "NEEDED *libpython"`) {
  267.                                     $has_extension=1;
  268.                                 }
  269.                         }, $curdir ;
  270.                         if ( ($has_module or $has_extension) and not grep { $_ eq "$curdir" } @dirlist ) {
  271.                                 if ( $useversion ) {
  272.                                 # Create .pyversion to tell update-python-modules for which
  273.                                 # version to compile
  274.                                     open(VERFILE, "> $curdir/.pyversion") ||
  275.                                         error("Can't create $curdir/.pyversion: $!");
  276.                                     print VERFILE "$useversion\n";
  277.                                     close(VERFILE);
  278.                                     $need_verdep{$useversion}=1;
  279.                                 } else {
  280.                                     $need_pydep=1;
  281.                                     $strong_pydep=1 if $has_extension;
  282.                                 }
  283.                 $curdir =~ s%^$tmp%%;
  284.                                 push @dirlist, "$curdir" if $has_module;
  285.                         }
  286.                 }
  287.         }
  288.     if (@dirlist) {
  289.         # We have private python modules
  290.         # Use python-support to ensure that they are always
  291.         # byte-compiled for the current version
  292.         mkdir("$tmp/usr/share/python-support");
  293.         open(DIRLIST, "> $tmp/usr/share/python-support/$package.dirs") ||
  294.             error("Can't create $tmp/usr/share/python-support/$package.dirs: $!");
  295.         print DIRLIST map "$_\n", @dirlist;
  296.         close(DIRLIST);
  297.         $do_scripts = "$do_scripts $package.dirs";
  298.     }
  299.  
  300.     # 3) Add python-support dependency depending on what we found
  301.         if (-d "$tmp/usr/share/python-support") {
  302.         # Namespace packages were introduced in 0.7.1
  303.             addsubstvar($package, "python:Depends", "python-support (>= 0.7.1)");
  304.         }
  305.         
  306.            # 4) Look for python scripts
  307.            find sub {
  308.         return unless -f and -x;
  309.         return if excludefile($File::Find::name);
  310.         local *F;
  311.                return unless open F, $_;
  312.         if (read F, local $_, 32 and m%^#!\s*/usr/bin/(env\s+)?(python(\d+\.\d+)?)\s%) {
  313.                    if ( "python" eq $2 ) {
  314.                 $need_pydep=1;
  315.                    } elsif (defined $need_verdep{$3}) {
  316.                        $need_verdep{$3}=1;
  317.                    }
  318.                }
  319.                close F;
  320.            }, $tmp;
  321.            
  322.            # 5) Generate remaining dependencies
  323.            foreach (@allversions) {
  324.                if ($need_verdep{$_}) {
  325.                    addsubstvar($package, "python:Depends", "python$_");
  326.                }
  327.            }
  328.            if (not $have_pydep) {
  329.                if ($strong_pydep) {
  330.                    addsubstvar($package, "python:Depends", "python (>= $default)");
  331.                    my $maxversion = next_minor_version($default);
  332.                    addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  333.                    $have_pydep=1;
  334.                } elsif ($need_pydep and -f "debian/pyversions") {
  335.                    my $supported=`pysupport-parseversions --minmax debian/pyversions`;
  336.                    my @ar=split "\n",$supported;
  337.                    my @minmax=split " ",$ar[1];
  338.                 my $minversion=$minmax[0];
  339.                 if ($minversion ne "None") {
  340.                     addsubstvar($package, "python:Depends", "python (>= $minversion)");
  341.                     $have_pydep=1;
  342.             }
  343.             my $maxversion=$minmax[1];
  344.                 if ($maxversion ne "None") {
  345.                 $maxversion = next_minor_version($maxversion);
  346.                 addsubstvar($package, "python:Depends", "python (<< $maxversion)");
  347.                 $have_pydep=1;
  348.             }
  349.                }
  350.            }
  351.            # If nothing has added a python dependency yet, add it
  352.     if ($need_pydep and not $have_pydep) {
  353.                addsubstvar($package, "python:Depends", "python");
  354.     }
  355.     
  356.     # 6) Generate the scripts
  357.     if ($do_scripts && ! $dh{NOSCRIPTS}) {
  358.         autoscript($package, "postinst", "postinst-python-support", "s,#ARGS#,$do_scripts,");
  359.         autoscript($package, "prerm",    "prerm-python-support",    "s,#ARGS#,$do_scripts,");
  360.     }
  361. }
  362.  
  363. =head1 SEE ALSO
  364.  
  365. L<debhelper(7)>
  366.  
  367. This program is a part of python-support but is made to work with debhelper.
  368.  
  369. =head1 AUTHORS
  370.  
  371. Josselin Mouette <joss@debian.org>,
  372. Raphael Hertzog <hertzog@debian.org>
  373.  
  374. =cut
  375.